using NFreeMarker.Template;

namespace NFreeMarker.Core
{
    /**
     * An instruction to visit an XML node.
     */

    public sealed class VisitNode : TemplateElement // NOTE: Was internal
    {
        private readonly Expression _targetNode;
        private readonly Expression _namespaces;

        internal VisitNode(Expression targetNode, Expression namespaces)
        {
            _targetNode = targetNode;
            _namespaces = namespaces;
        }

        internal override void Accept(Environment env)
        {
            ITemplateModel node = _targetNode.GetAsTemplateModel(env);
            AssertNonNull(node, _targetNode, env);
            if (!(node is ITemplateNodeModel))
            {
                throw new TemplateException("Expecting an XML node here", env);
            }
            ITemplateModel nss = _namespaces == null ? null : _namespaces.GetAsTemplateModel(env);
            if (_namespaces is StringLiteral)
            {
                nss = env.ImportLib(((ITemplateScalarModel) nss).GetAsString(), null);
            }
            else if (_namespaces is ListLiteral)
            {
                nss = ((ListLiteral) _namespaces).EvaluateStringsToNamespaces(env);
            }
            if (nss != null)
            {
                if (nss is Environment.Namespace)
                {
                    var ss = new SimpleSequence(1);
                    ss.Add(nss);
                    nss = ss;
                }
                else if (!(nss is ITemplateSequenceModel))
                {
                    throw new TemplateException("Expecting a sequence of namespaces after 'using'", env);
                }
            }
            env.Visit((ITemplateNodeModel) node, (ITemplateSequenceModel) nss);
        }

        public override string GetCanonicalForm()
        {
            if (_namespaces == null)
            {
                return "<#visit " + _targetNode.GetCanonicalForm() + "/>";
            }
            return "<#visit " + _targetNode.GetCanonicalForm() + " using " + _namespaces.GetCanonicalForm() + "/>";
        }

        public override string GetDescription()
        {
            return "visit instruction";
        }
    }
}